package edu.pku.taas.hyperic.monitor;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.hqapi1.AgentApi;
import org.hyperic.hq.hqapi1.ResourceApi;
import org.hyperic.hq.hqapi1.XmlUtil;
import org.hyperic.hq.hqapi1.types.Agent;
import org.hyperic.hq.hqapi1.types.AgentsResponse;
import org.hyperic.hq.hqapi1.types.PingAgentResponse;
import org.hyperic.hq.hqapi1.types.Resource;
import org.hyperic.hq.hqapi1.types.ResourcesResponse;
import org.hyperic.hq.hqapi1.types.ResponseStatus;

public class CopyOfCloudResourceTree {
	private static List MONITOR_PROTOTYPE_LIST = new ArrayList();
	private static List OS_TYPE_LIST = new ArrayList();
	private static Agent _localAgent = null;
	private static Log log = LogFactory.getLog(CopyOfCloudResourceTree.class);

	protected Log getLog() {
		return log;
	}

	public CopyOfCloudResourceTree() {
		LogConfigure.setUp();
		log.info("common log set up ok");
		
		// 10123
		int[] monitorTypes = { 10113, 10126, 10131, 10132, 10141, 10142, 10159, 10316, 10341, 10415, 10424 };
		// removed :10125--network server; 10124--process server;10143 xen vm
		// hostserver:removed vm metrics:10146 Xen Host CPU;10145;10148,10147,10144
		for (int i : monitorTypes)
			MONITOR_PROTOTYPE_LIST.add(i);

		int[] osTypes = { 10113, 10141 };
		for (int i : osTypes)
			OS_TYPE_LIST.add(i);

	}

	public String getSerializedCloudResourceTree() throws Exception {
		return serializeAllResourcesInCloud().toString();
	}
	
	public StringBuilder serializeAllResourcesInCloud() throws Exception {

		AgentApi api = HQApiHelper.getApi().getAgentApi();

		AgentsResponse response = api.getAgents();
		System.out.println("--------------get Agent:" + response.getAgent().size());

		System.out.println();
		// XmlUtil.serialize(response, System.out, true);
		System.out.println();
		if (response.getStatus().equals(ResponseStatus.FAILURE)) {
			String err = "Error querying agents: " + response.getError().getReasonText();
			log.error(err);
			throw new Exception(err);
		}

		System.out.println("--------------get Agent:" + response.getAgent().size());

		System.out.println("begin to print resource:");
		System.out.println("--------------------------------------------------");

		StringBuilder builder = new StringBuilder();
		addXMLHead(builder);
		builder.append("<cloud-resources cloud-master-name=\"xenserver161\" cloud-master-ip=\"192.168.0.164\">\n");
		// builder.append("<cloud-master name=\"xenserver161\" ip=\"192.168.0.164\"/>\n");
		builder.append("<cluster-resources cluster-master-name=\"localhost.localdomain\" cluster-master-ip=\"192.168.0.161\">\n");
		// builder.append("<cluster-master name=\"localhost.localdomain\" ip=\"192.168.0.161\"/>\n");
		for (Agent a : response.getAgent()) {
			PingAgentResponse pingRespnse = api.pingAgent(a);
			boolean isUp = pingRespnse.getStatus().equals(ResponseStatus.SUCCESS) && pingRespnse.isUp();
			System.out
					.println("#resource on agent id=" + a.getId() + "  ip=" + a.getAddress() + " port=" + a.getPort() + " is up? " + isUp);

			serializePlatformResourceRecursively(a, builder);
			System.out.println("--------------------------------------------------");
		}
		builder.append("</cluster-resources>\n");
		builder.append("</cloud-resources>\n");
		System.out.println("##############################resources xml file############################");
		System.out.println(builder.toString());
		
		return builder;
	}

	private void serializePlatformResourceRecursively(Agent a, StringBuilder builder) throws Exception {
		// Agent a = getRunningAgent();

		ResourceApi api = HQApiHelper.getApi().getResourceApi();
		// System.out.println("ResourceApi=" + api);
		ResourcesResponse findResponse = api.getResources(a, false, true);

		// XmlUtil.serialize(findResponse, System.out, true);

		System.out.println("----------------");

		System.out.println("Found getResource: " + findResponse.getResource().size());
		System.out.println("----------------");

		serializeResource(findResponse.getResource(), 0, builder);
	}

	private void addXMLHead(StringBuilder builder) {
		builder.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>").append("\n");

	}

	public void serializeResource(List<Resource> rlo, int level, StringBuilder builder) {
		for (Resource r : rlo) {
			serializeResource(r, level, builder);
		}

	}

	public void serializeResource(Resource r, int level, StringBuilder builder) {

		if (isInTheMonitorTypeList(r.getResourcePrototype().getId())) {

			builder.append("<Resource id=\"").append(r.getId()).append("\" ").append(" resourceType=\"").append(level).append("\"").append(" name=\"").append(r.getName()).append("\" ").append(
					" description=\"").append(r.getDescription()).append("\" >").append("\n")
			// end of resource
					.append(" <ResourcePrototype id=\"").append(r.getResourcePrototype().getId()).append("\" ").append(" name=\"").append(
							r.getResourcePrototype().getName()).append("\"/>").append("\n")// end of ResourcePrototype
			;

			if (isInTheOSTypeList(r.getResourcePrototype().getId())) {
				builder.append(" <Agent id=\"").append(r.getAgent().getId()).append("\" ").append(" address=\"").append(
						r.getAgent().getAddress()).append("\" ").append(" port=\"").append(r.getAgent().getPort()).append("\" />").append(
						"\n")
						// end of agent
						.append(" <Ip address=\"").append(r.getIp().get(0).getAddress()).append("\" ").append(" mac=\"").append(
								r.getIp().get(0).getMac()).append("\" ").append(" netmask=\"").append(r.getIp().get(0).getNetmask())
						.append("\" />").append("\n")// end of ip

				;
			}

			// printResource recursively
			List<Resource> rl = r.getResource();
			serializeResource(rl, (++level), builder);

			builder.append(" </Resource> ");
		} else {
			List<Resource> rl = r.getResource();
			serializeResource(rl, level, builder);
		}

	}

	private boolean isInTheMonitorTypeList(int typeId) {
		return MONITOR_PROTOTYPE_LIST.contains(typeId);
	}

	private boolean isInTheOSTypeList(int typeId) {
		return OS_TYPE_LIST.contains(typeId);
	}

	/**
	 * Get the locally running agent.
	 * 
	 * @return The locally running agent or null if one does not exist.
	 * @throws Exception
	 *             If a running agent could not be found.
	 */
	protected Agent getRunningAgent() throws Exception {

		if (_localAgent != null) {
			return _localAgent;
		}

		AgentApi api = HQApiHelper.getApi().getAgentApi();

		AgentsResponse response = api.getAgents();
		System.out.println("--------------get Agent:" + response.getAgent().size());

		System.out.println();
		XmlUtil.serialize(response, System.out, true);
		System.out.println();
		if (response.getStatus().equals(ResponseStatus.FAILURE)) {
			String err = "Error querying agents: " + response.getError().getReasonText();
			log.error(err);
			throw new Exception(err);
		}

		System.out.println("--------------get Agent:" + response.getAgent().size());

		for (Agent a : response.getAgent()) {
			System.out.println("agent# ip=" + a.getAddress());
			System.out.println("agent# id=" + a.getId());
			System.out.println("agent# port=" + a.getPort());
			System.out.println("####");
			PingAgentResponse pingRespnse = api.pingAgent(a);
			if (pingRespnse.getStatus().equals(ResponseStatus.SUCCESS) && pingRespnse.isUp()) {
				System.out.println("agent# id=" + a.getId() + " is up!");
				if ("192.168.0.161".equals(a.getAddress())) {
					_localAgent = a;
					return _localAgent;
				}

			}
		}

		String err = "No running agents found.";
		log.error(err);
		throw new Exception(err);
	}

	public static void main(String[] args) throws Exception {
		CopyOfCloudResourceTree tm = new CopyOfCloudResourceTree();
		tm.serializeAllResourcesInCloud();

		// System.out.println("begin to get log:");
		// try {
		// new LogConfigure().setUp();
		// log.info("common log set up ok");
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
	}

}
